import { app, BrowserWindow, shell, ipcMain,Menu } from 'electron' // 从 electron 模块导入需要使用的类
import { createRequire } from 'node:module' // 从 node.js 的 module 模块导入 createRequire 函数
import { fileURLToPath } from 'node:url' // 从 node.js 的 url 模块导入 fileURLToPath 函数
import path from 'node:path' // 从 node.js 导入路径处理模块
import os from 'node:os' // 从 node.js 导入操作系统信息模块

const require = createRequire(import.meta.url) // 创建一个 require 函数，用于加载 CommonJS 模块
const __dirname = path.dirname(fileURLToPath(import.meta.url)) // 获取当前文件所在目录的绝对路径

// The built directory structure
//
// ├─┬ dist-electron
// │ ├─┬ main
// │ │ └── index.js    > Electron-Main
// │ └─┬ preload
// │   └── index.mjs   > Preload-Scripts
// ├─┬ dist
// │ └── index.html    > Electron-Renderer
//

// 定义构建后的目录结构
process.env.APP_ROOT = path.join(__dirname, '../..') // 设置环境变量 APP_ROOT 为项目根目录

export const MAIN_DIST = path.join(process.env.APP_ROOT, 'dist-electron') // 主进程文件夹路径
export const RENDERER_DIST = path.join(process.env.APP_ROOT, 'dist') // 渲染进程文件夹路径
export const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL // 开发服务器 URL（如果有的话）

// 根据是否处于开发模式设置公共资源路径
process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL
  ? path.join(process.env.APP_ROOT, 'public')
  : RENDERER_DIST

// 对于 Windows 7 系统禁用 GPU 加速
if (os.release().startsWith('6.1')) app.disableHardwareAcceleration()

// 如果是 Windows 10 或更高版本，设置应用模型 ID 以便显示通知
if (process.platform === 'win32') app.setAppUserModelId(app.getName())

// 单实例锁：确保同一时间只能运行一个应用实例
if (!app.requestSingleInstanceLock()) {
  app.quit() // 如果已经有一个实例在运行，则退出新启动的应用
  process.exit(0)
}

let win: BrowserWindow | null = null // 声明一个全局的 BrowserWindow 变量
const preload = path.join(__dirname, '../preload/index.mjs') // 预加载脚本路径
const indexHtml = path.join(RENDERER_DIST, 'index.html') // 主窗口加载的 HTML 文件路径

async function createWindow() { // 创建主窗口的异步函数
  win = new BrowserWindow({ // 创建一个新的 BrowserWindow 实例
    title: 'Main window', // 窗口标题
    icon: path.join(process.env.VITE_PUBLIC, 'favicon.ico'), // 窗口图标
    width: 1366, // 设置窗口宽度为 800 像素
    height: 768, // 设置窗口高度为 600 像素
    webPreferences: { // Web 页面偏好设置
      preload, // 预加载脚本
      // 注意：在生产环境中启用 nodeIntegration 和禁用 contextIsolation 是不安全的做法
      // nodeIntegration: true,
      // 考虑使用 contextBridge.exposeInMainWorld
      // 更多信息请参阅 https://www.electronjs.org/docs/latest/tutorial/context-isolation
      // contextIsolation: false,
    },
  })

  if (VITE_DEV_SERVER_URL) { // 如果存在开发服务器 URL
    win.loadURL(VITE_DEV_SERVER_URL) // 加载开发服务器上的页面
    // 在非打包模式下打开开发者工具
    win.webContents.openDevTools()
  } else {
    win.loadFile(indexHtml) // 否则加载本地的 HTML 文件
  }

  // 当页面加载完成后向渲染进程发送消息
  win.webContents.on('did-finish-load', () => {
    win?.webContents.send('main-process-message', new Date().toLocaleString())
  })

  // 让所有链接都在默认浏览器中打开，而不是在应用内
  win.webContents.setWindowOpenHandler(({ url }) => {
    if (url.startsWith('https:')) shell.openExternal(url) // 如果链接是以 https 开头，在系统默认浏览器中打开
    return { action: 'deny' } // 不允许在应用内打开新窗口
  })
  // win.webContents.on('will-navigate', (event, url) => { }) #344

    Menu.setApplicationMenu(null)
}

app.whenReady().then(createWindow) // 当 Electron 应用准备就绪时调用 createWindow 函数

// 所有窗口关闭时的行为
app.on('window-all-closed', () => {
  win = null
  if (process.platform !== 'darwin') app.quit() // 在 macOS 外的平台上，如果没有窗口打开就退出应用
})

// 当应用被激活且没有窗口时的行为
app.on('second-instance', () => {
  if (win) {
    if (win.isMinimized()) win.restore() // 如果窗口最小化了，恢复它
    win.focus() // 将焦点移到窗口上
  }
})

app.on('activate', () => {
  const allWindows = BrowserWindow.getAllWindows() // 获取所有窗口
  if (allWindows.length) {
    allWindows[0].focus() // 如果有窗口，将焦点移到第一个窗口
  } else {
    createWindow() // 如果没有窗口，创建一个新的窗口
  }
})

// 处理来自渲染进程的 'open-win' 请求
ipcMain.handle('open-win', (_, arg) => {
  const childWindow = new BrowserWindow({
    webPreferences: {
      preload,
      nodeIntegration: true, // 允许 Node.js 集成
      contextIsolation: false, // 禁用上下文隔离
    },
  })

  if (VITE_DEV_SERVER_URL) {
    childWindow.loadURL(`${VITE_DEV_SERVER_URL}#${arg}`) // 如果是在开发环境下，加载带有哈希参数的开发服务器 URL
  } else {
    childWindow.loadFile(indexHtml, { hash: arg }) // 否则加载带有哈希参数的本地 HTML 文件
  }
})